package com.example.learnvideo.service

import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.Service
import android.content.Intent
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.net.Uri
import android.os.*
import android.util.Log
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.example.learnvideo.MainApplication
import com.example.learnvideo.R
import com.example.learnvideo.util.BitmapUtil
import com.example.learnvideo.util.DateUtil
import com.example.learnvideo.util.Utils
import com.example.learnvideo.widget.FloatWindow

class CaptureService : Service() {

    // 声明一个媒体投影管理器对象
    private lateinit var mediaManager:MediaProjectionManager
    // 声明一个媒体投影对象
    private var mp:MediaProjection? = null
    // 声明一个图像读取器对象
    private lateinit var mImageReader:ImageReader
    // 文件路径
    private var imagePath = ""
    // 屏幕宽度，屏幕高度，每英寸的像素数
    private var mScreenWidth = 0
    private var mScreenHeight = 0
    private var mScreenDensity = 0
    // 声明一个虚拟显示层对象
    private var mVirtualDisplay:VirtualDisplay? = null
    // 声明一个悬浮窗对象
    private var mFloatWindow:FloatWindow? = null
    // App的应用单例
    private lateinit var myApp:MainApplication

    private val mHandler = Handler(Looper.getMainLooper())

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    @SuppressLint("WrongConstant")
    override fun onCreate() {
        super.onCreate()
        myApp = MainApplication.getInstance()
        mediaManager = myApp.manager!!
        mScreenWidth = Utils.getScreenWidth(this)
        mScreenHeight = Utils.getScreenHeight(this)
        // 获得屏幕每英寸中的像素数
        mScreenDensity = Utils.getScreenDensityDpi(this)
        // 根据屏幕宽高创建一个新的图像读取器
        mImageReader = ImageReader.newInstance(mScreenWidth,mScreenHeight,PixelFormat.RGBA_8888,2)
        if (mFloatWindow == null){
            // 创建一个新的悬浮窗
            mFloatWindow = FloatWindow(myApp)
            // 设置悬浮窗的布局内容
            mFloatWindow?.setLayout(R.layout.float_capture)
        }
        // 设置悬浮窗的点击监听器
        mFloatWindow?.setOnFloatListener {
            // 准备屏幕
            mHandler.post(mStartVirtual)
            // 延迟500毫秒后截屏
            mHandler.postDelayed(mCapture,500)
            // 延迟1000毫秒后释放屏幕
            mHandler.postDelayed(mStopVirtual,1000)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        if (mFloatWindow != null && mFloatWindow!!.isShow){
            mFloatWindow?.close()
        }
        if (mp != null){
            // 停止媒体投影
            mp?.stop()
        }
    }

    // 绑定前台服务。要先创建通知渠道，创建代码见MainApplication.java
    private fun bindForegroundService(){
        // 创建一个通知消息的建造器
        var builder = Notification.Builder(this)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            // Android 8.0开始必须给每个通知分配对应的渠道
            builder = Notification.Builder(this,getString(R.string.app_name))
        }
        builder.setAutoCancel(false) // 点击通知栏后是否自动清除该通知
            .setSmallIcon(R.mipmap.ic_launcher) // 设置应用名称左边的小图标
            .setContentTitle(getString(R.string.app_name)) // 设置通知栏里面的标题文本
            .setContentText("截屏服务") // 设置通知栏里面的内容文本
        val notify = builder.build() // 根据通知建造器构建一个通知对象
        startForeground(1,notify) // 把服务推送到前台的通知栏
    }

    // 定义一个屏幕截取任务
    private val mCapture = Thread{
        // 生成截图文件的保存路径
        imagePath = "${getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString()}/${DateUtil.getNowDateTime()}.png"
        Log.d("CaptureService","imagePath = $imagePath")
        // 从图像读取器中获取最近的一个Image对象
        val image = mImageReader.acquireLatestImage()
        // 把Image对象转换成位图对象
        val bitmap = BitmapUtil.getBitmap(image)
        // 把位图对象保存为图片文件
        BitmapUtil.saveImage(imagePath,bitmap)
        // 通知相册来了张新图片

        BitmapUtil.notifyPhotoAlbum(this,imagePath)
        Toast.makeText(this,"截图成功：${imagePath}",Toast.LENGTH_SHORT).show()
    }

    // 定义一个屏幕释放任务
    private val mStopVirtual = Thread{
        // 完成截图后再恢复悬浮窗
        mFloatWindow!!.mContentView.visibility = View.VISIBLE
        if (mVirtualDisplay != null){
            // 释放虚拟显示层资源
            mVirtualDisplay?.release()
            mVirtualDisplay = null
        }
        // 显示缩略图窗口
        showThumbnail()
    }

    // 定义一个屏幕准备任务
    private val mStartVirtual = Thread{
        // 截图过程中先隐藏悬浮窗
        mFloatWindow!!.mContentView.visibility = View.GONE
        if (mp == null){
            // 根据结果代码和结果意图，从媒体投影管理器中获取一个媒体投影对象
            mp = mediaManager.getMediaProjection(myApp.mResultCode,myApp.mResultIntent!!)
        }
        // 根据屏幕宽高创建一个虚拟显示层
        mVirtualDisplay = mp?.createVirtualDisplay("capture_screen",mScreenWidth,mScreenHeight,
        mScreenDensity,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,mImageReader.surface,null,null)
    }

    // 显示缩略图窗口
    private fun showThumbnail(){
        // 创建一个新的悬浮窗
        val thumb = FloatWindow(MainApplication.context)
        thumb.setLayout(R.layout.float_thumb)
        val ivThumb = thumb.mContentView.findViewById<ImageView>(R.id.iv_thumb)
        thumb.setOnFloatListener {
            val intent = Intent(Intent.ACTION_VIEW)
            intent.type = "vnd.android.cursor.dir/image"
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            startActivity(intent)
            mHandler.post{thumb.close()}
        }
        thumb.show(Gravity.RIGHT or Gravity.BOTTOM)
        // 设置图像视图的路径对象
        ivThumb.setImageURI(Uri.parse(imagePath))
        mHandler.postDelayed({thumb.close()},2000)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (mFloatWindow != null && !mFloatWindow!!.isShow){
            //显示悬浮窗
            mFloatWindow?.show(Gravity.LEFT or Gravity.TOP)
        }
        // 绑定前台服务（从Android10开始，媒体投影操作必须在前台服务中运行）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            bindForegroundService()
        }
        return super.onStartCommand(intent, flags, startId)
    }
}